package com.mikufufu.blog.security.filter;

import com.mikufufu.blog.common.constant.ContentType;
import com.mikufufu.blog.common.constant.HttpStatus;
import com.mikufufu.blog.common.entity.AjaxResult;
import com.mikufufu.blog.common.entity.SysUser;
import com.mikufufu.blog.security.TokenStore;
import com.mikufufu.blog.utils.I18Utils;
import com.mikufufu.blog.utils.StringUtils;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;

/**
 * Token过滤器
 * 
 */
@Slf4j
public class TokenFilter extends OncePerRequestFilter {

    private final String[] loginUrl = {"/login","/admin/login","/register"};

    @Override
    protected void doFilterInternal(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull FilterChain chain) throws ServletException, IOException {

        // 放行登录接口
        if (Arrays.stream(loginUrl).anyMatch(url -> url.contains(request.getRequestURI()))){
            chain.doFilter(request, response);
            return;
        }

        String token = request.getHeader("Authorization");
        if (StringUtils.isBlank(token)) {
            chain.doFilter(request, response);
            // 放行后不在执行后续过滤器
            return;
        }
        // 从请求头中的token获取用户信息
        SysUser user = TokenStore.getSysUserInToken(token);
        if (StringUtils.isNotEmpty(user)) {
            // 将认证对象设置到Security上下文中
            SecurityContextHolder.getContext().setAuthentication(
                    new UsernamePasswordAuthenticationToken(user,token,user.getAuthorities())
            );
            log.debug("用户{}认证成功",user.getUsername());
            // 继续执行过滤器链
            chain.doFilter(request, response);
        }else {
            response.setContentType(ContentType.JSON_UTF8);
            log.debug("token无效");
            // 将认证失败的信息封装为JSON格式，并写入响应体中
            response.getWriter().write(JSON.toJSONString(AjaxResult.error(HttpStatus.UNAUTHORIZED, I18Utils.getMessage("user.token.invalid"))));
        }
    }
}
